using System;
using UnityEngine;
using UnityEngine.EventSystems;

public class OperateArea : MonoBehaviour
{
	public interface IAreaOperation
	{
		void DragBegin(Vector2 position);

		void Drag(Vector2 position);

		void DragEnd(Vector2 position);

		void Click(Vector2 position);

		void Begin();

		void End();
	}

	public class PointerOperation : IAreaOperation
	{
		private Vector2 poolBallsp;

		private Vector2 lastTouchsp;

		public void DragBegin(Vector2 position)
		{
			poolBallsp = Pools.CueBall.GetScreenPosition();
			lastTouchsp = position;
		}

		public void Drag(Vector2 position)
		{
			if (lastTouchsp == default(Vector2))
			{
				lastTouchsp = position;
				return;
			}
			Vector3 lhs = lastTouchsp - poolBallsp;
			Vector3 rhs = position - poolBallsp;
			float num = Mathf.Acos(Vector3.Dot(lhs.normalized, rhs.normalized)) * 57.29578f;
			if (!float.IsNaN(num) && !float.IsInfinity(num) && num != 0f)
			{
				float num2 = num * 100f / Mathf.Max(rhs.magnitude, 100f);
				Vector3 vector = Vector3.Cross(lhs, rhs);
				float z = vector.z;
				if (z < 0f)
				{
					Pools.Cue.Rotate(num2);
				}
				else
				{
					Pools.Cue.Rotate(0f - num2);
				}
				lastTouchsp = position;
			}
		}

		public void DragEnd(Vector2 position)
		{
		}

		public void Click(Vector2 position)
		{
			PointerAt(position);
		}

		public void PointerAt(Vector3 point)
		{
			Vector2 v = point - Pools.CueBall.GetScreenPosition();
			Vector2 v2 = BaseUIController.cueAndLines.GetPointerDirection();
			float num = Mathf.Acos(Vector3.Dot(v.normalized, v2.normalized)) * 57.29578f;
			float angle = num;
			Vector3 vector = Vector3.Cross(v, v2);
			PointerAtAngle(angle, vector.z < 0f);
		}

		public float GetRotationAngleAtWorld(Vector3 point)
		{
			Vector2 v = Pools.SceneCamera.WorldToScreenPoint(point) - Pools.CueBall.GetScreenPosition();
			Vector2 v2 = BaseUIController.cueAndLines.GetPointerDirection();
			float num = Mathf.Acos(Vector3.Dot(v.normalized, v2.normalized)) * 57.29578f;
			float num2 = num;
			Vector3 vector = Vector3.Cross(v, v2);
			return num2 * (float)((!(vector.z < 0f)) ? 1 : (-1));
		}

		public void PointerAtWorld(Vector3 point)
		{
			Vector3 point2 = Pools.SceneCamera.WorldToScreenPoint(point);
			PointerAt(point2);
		}

		public void PointerAtAngle(float angle, bool anticlockwise)
		{
			if (!float.IsNaN(angle) && !float.IsInfinity(angle))
			{
				if (anticlockwise)
				{
					Pools.Cue.Rotate(0f - angle);
				}
				else
				{
					Pools.Cue.Rotate(angle);
				}
			}
		}

		public void Begin()
		{
			BaseUIController.fireSlider.Show();
			BaseUIController.cueAndLines.gameObject.SetActive(value: true);
			if (DragOperation.lastPointerPosition != Vector2.zero)
			{
				PointerAt(DragOperation.lastPointerPosition);
				DragOperation.lastPointerPosition = Vector2.zero;
			}
		}

		public void End()
		{
			BaseUIController.cueAndLines.gameObject.SetActive(value: false);
			BaseUIController.fireSlider.Hide();
		}
	}

	public class DragOperation : IAreaOperation
	{
		private Vector3 ballDelta = default(Vector3);

		private WhiteBall cueBall;

		private Constraint constraint;

		private Vector2 prevScreenPosition;

		private float y;

		private bool droppable = true;

		public static Vector2 lastPointerPosition = Vector2.zero;

		public DragOperation()
		{
			cueBall = Pools.CueBall;
			constraint = Pools.CueBall.GetComponent<Constraint>();
		}

		public void DragBegin(Vector2 position)
		{
			prevScreenPosition = position;
		}

		public void Drag(Vector2 position)
		{
			Vector3 vector = Pools.SceneCamera.ScreenToWorldPoint(position) - Pools.SceneCamera.ScreenToWorldPoint(prevScreenPosition);
			ballDelta.Set(vector.x, vector.y, vector.z);
			prevScreenPosition = position;
			Vector3 position2 = cueBall.transform.position;
			position2 += ballDelta;
			position2 = MathTools.Clamp3(position2, constraint.min, constraint.max);
			cueBall.transform.position = position2;
			if (RayCast(Pools.SceneCamera.WorldToScreenPoint(position2)))
			{
				droppable = false;
				BaseUIController.hand.ChangeState(1);
			}
			else
			{
				droppable = true;
				BaseUIController.hand.ChangeState(0);
			}
		}

		public void DragEnd(Vector2 position)
		{
		}

		public void Click(Vector2 position)
		{
			if (droppable)
			{
				Vector3 position2 = cueBall.transform.position;
				position2.y = y;
				cueBall.transform.position = position2;
				lastPointerPosition = position;
				GameManager.Rules.State = GlobalState.IDLE;
			}
		}

		public void Begin()
		{
			Pools.Cue.Hide();
			BaseUIController.hand.Show();
			BaseUIController.hand.Locate(cueBall.transform.position);
			Vector3 position = cueBall.transform.position;
			y = position.y;
			cueBall.yConstrain = false;
			Vector3 position2 = cueBall.transform.position;
			position2.y = 0f;
			cueBall.transform.position = position2;
			constraint.enabled = true;
			cueBall.GetComponent<Rigidbody>().useGravity = false;
			cueBall.GetComponent<Rigidbody>().constraints = (RigidbodyConstraints)116;
			cueBall.GetComponent<Collider>().isTrigger = true;
			BaseUIController.cueAndLines.gameObject.SetActive(value: false);
		}

		public void End()
		{
			Pools.Cue.Show();
			BaseUIController.cueAndLines.gameObject.SetActive(value: true);
			Vector3 position = cueBall.transform.position;
			position.y = y;
			cueBall.transform.position = position;
			BaseUIController.hand.Hide();
			cueBall.GetComponent<Rigidbody>().useGravity = true;
			cueBall.GetComponent<Rigidbody>().constraints = RigidbodyConstraints.None;
			constraint.enabled = false;
			cueBall.GetComponent<Collider>().isTrigger = false;
		}

		private bool RayCast(Vector2 p)
		{
			Vector3 origin = Pools.SceneCamera.ScreenToWorldPoint(p);
			Vector3 down = Vector3.down;
			Ray ray = new Ray(origin, down);
			if (Physics.SphereCast(ray, Pools.CueBall.GetRadius(), 1000f, 1 << LayerMask.NameToLayer("Ball")))
			{
				return true;
			}
			return false;
		}
	}

	private class DontDoAnyOperation : IAreaOperation
	{
		public void DragBegin(Vector2 position)
		{
		}

		public void Drag(Vector2 position)
		{
		}

		public void DragEnd(Vector2 position)
		{
		}

		public void Click(Vector2 position)
		{
		}

		public void Begin()
		{
		}

		public void End()
		{
		}
	}

	private Delegate1Args<Vector2> m_OnDrag;

	private Delegate1Args<Vector2> m_OnDragBegin;

	private Delegate1Args<Vector2> m_OnDragEnd;

	private Delegate1Args<Vector2> m_OnClick;

	public PointerOperation pointerOperation;

	public DragOperation dragOperation;

	private DontDoAnyOperation m_DontDoAnyOperation;

	private bool m_Dragging;

	private IAreaOperation m_Operation;

	public IAreaOperation current => m_Operation;

	private void Awake()
	{
		PoolRulesBase.onNewTurn = (Delegate1Args<int>)Delegate.Combine(PoolRulesBase.onNewTurn, new Delegate1Args<int>(RoundBegin));
	}

	private void Start()
	{
		pointerOperation = new PointerOperation();
		dragOperation = new DragOperation();
		m_DontDoAnyOperation = new DontDoAnyOperation();
	}

	private void RoundBegin(int playerID)
	{
		Pools.Cue.Reset();
		PoolRulesBase.onNewTurn = (Delegate1Args<int>)Delegate.Remove(PoolRulesBase.onNewTurn, new Delegate1Args<int>(RoundBegin));
	}

	public void ChangeOperationType(GlobalState state)
	{
		switch (state)
		{
		case GlobalState.DRAG_WHITEBALL:
			SetOpeartion(dragOperation);
			break;
		case GlobalState.IDLE:
			SetOpeartion(pointerOperation);
			break;
		default:
			SetOpeartion(m_DontDoAnyOperation);
			break;
		}
	}

	private void SetOpeartion(IAreaOperation operation)
	{
		if (m_Operation != null)
		{
			if (m_Operation.GetType() == operation.GetType())
			{
				return;
			}
			m_Operation.End();
		}
		m_Operation = operation;
		IAreaOperation operation2 = m_Operation;
		m_OnDrag = operation2.Drag;
		IAreaOperation operation3 = m_Operation;
		m_OnClick = operation3.Click;
		IAreaOperation operation4 = m_Operation;
		m_OnDragBegin = operation4.DragBegin;
		IAreaOperation operation5 = m_Operation;
		m_OnDragEnd = operation5.DragEnd;
		m_Operation.Begin();
	}

	public void OnAreaDragEnd(BaseEventData data)
	{
		if (m_OnDragEnd != null && m_Dragging)
		{
			Vector3 v = ((PointerEventData)data).position;
			m_OnDragEnd(v);
		}
		m_Dragging = false;
	}

	public void OnAreaDrag(BaseEventData data)
	{
		PointerEventData pointerEventData = data as PointerEventData;
		if (m_OnDrag != null)
		{
			m_OnDrag(pointerEventData.position);
		}
	}

	public void OnAreaDragBegin(BaseEventData data)
	{
		m_Dragging = true;
		if (m_OnDragBegin != null)
		{
			Vector3 v = ((PointerEventData)data).position;
			m_OnDragBegin(v);
		}
	}

	public void OnAreaPointerClick(BaseEventData data)
	{
		if (!m_Dragging && m_OnClick != null)
		{
			Vector3 v = ((PointerEventData)data).position;
			m_OnClick(v);
		}
	}
}
